﻿/*+===================================================================
File:      GunBlock.cpp

Summary:   Định nghĩa các phương thức của CGunBlock.
===================================================================+*/

#include "GunMachine.h"
#include "PlayState.h"
#include "Explosion.h"

#define STATUS_CLOSE			0
#define STATUS_OPEN_QUARTER		1
#define STATUS_OPEN_HAFT		2
#define STATUS_CLOSE_HAFT		3
#define STATUS_CLOSE_QUARTER	4
#define STATUS_LEFT				5
#define STATUS_TOP				6
#define STATUS_UP				7
#define STATUS_CAN_OPEN			8
#define STATUS_CLOSE_FOREVER	9

#define MAX_BULLETS 3

CGunMachine::CGunMachine(CBill* bill, D3DXVECTOR2 pos, int id, int typeId) : CMoveableObject(pos, id, typeId)
{
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_GUN_MACHINE_CHANGE_QUATER);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_GUN_MACHINE_CHANGE_HAFT);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_GUN_MACHINE_LEFT);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_GUN_MACHINE_TOP);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_GUN_MACHINE_UP);
	m_bill = bill;

	m_pGun = new CGun(ID_ENEMY_SMALL_WHITE_BULLET, MAX_BULLETS, 1);

	m_box.width = 50;
	m_box.height = 50;

	m_nLife = 10;

	m_nStatus = STATUS_CAN_OPEN;
}

CGunMachine::~CGunMachine()
{
	if (m_pGun)
		delete m_pGun;
	if (m_bill)
		delete m_bill;
}

void CGunMachine::UpdateAnimation()
{
	switch (m_nStatus)
	{
		case STATUS_CLOSE:
		case STATUS_CLOSE_FOREVER:
		case STATUS_CAN_OPEN:
			m_pSprite = NULL;
			break;
		case STATUS_OPEN_QUARTER:
		case STATUS_CLOSE_QUARTER:
			m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_GUN_MACHINE_CHANGE_QUATER);
			break;
		case STATUS_OPEN_HAFT:
		case STATUS_CLOSE_HAFT:
			m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_GUN_MACHINE_CHANGE_HAFT);
			break;
		case STATUS_LEFT:
			m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_GUN_MACHINE_LEFT);
			break;
		case STATUS_TOP:
			m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_GUN_MACHINE_TOP);
			break;
		case STATUS_UP:
			m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_GUN_MACHINE_UP);
			break;
	}
}

void CGunMachine::Update(float timeFrame)
{
	if (!m_bIsLive)
		return;

	D3DXVECTOR2 billPos = m_bill->GetPos();

	if (g_nCurentLvl == ID_LEVEL2)
	{
		//// Khi bill đến khoảng cách nhất định -> mở GunMachine ra.
		if (m_nStatus == STATUS_CAN_OPEN && m_pos.y - 80 < billPos.y)
		{
			m_nStatus = STATUS_OPEN_QUARTER;
			m_fTimeAnimation = 0.2f;
		}

		//// Khi bill xa ra 1 khoảng cách nhất định -> đóng GunMachine lại.
		if ((m_nStatus == STATUS_LEFT || m_nStatus == STATUS_TOP || m_nStatus == STATUS_UP) && billPos.y > m_pos.y + 200)
		{
			m_nStatus = STATUS_CLOSE_FOREVER;
			m_fTimeAnimation = 0.2f;
		}
	}
	else
	{
		//// Khi bill đến khoảng cách nhất định -> mở GunMachine ra.
		if (m_nStatus == STATUS_CAN_OPEN &&  billPos.x + 200 > m_pos.x)
		{
			m_nStatus = STATUS_OPEN_QUARTER;
			m_fTimeAnimation = 0.2f;
		}

		//// Khi bill xa ra 1 khoảng cách nhất định -> đóng GunMachine lại.
		if ((m_nStatus == STATUS_LEFT || m_nStatus == STATUS_TOP || m_nStatus == STATUS_UP) && billPos.x > m_pos.x + 200)
		{
			m_nStatus = STATUS_CLOSE_HAFT
				
				;
			m_fTimeAnimation = 0.2f;
		}
	}

	// Hiệu ứng GunMachine mở ra.
	if (m_nStatus == STATUS_OPEN_QUARTER || m_nStatus == STATUS_OPEN_HAFT)
	{
		if (m_fTimeAnimation < 0.1f)
			m_nStatus = STATUS_OPEN_HAFT;

		if (m_fTimeAnimation > 0)
			m_fTimeAnimation -= timeFrame;
		else
		{
			m_fTimeAnimation = 0.0f;
			m_nStatus = STATUS_LEFT;
		}
	}

	// Hiệu ứng GunMachine đóng lại.
	if (m_nStatus == STATUS_CLOSE_HAFT || m_nStatus == STATUS_CLOSE_QUARTER)
	{
		if (m_fTimeAnimation < 0.1f)
			m_nStatus = STATUS_CLOSE_QUARTER;

		if (m_fTimeAnimation > 0)
			m_fTimeAnimation -= timeFrame;
		else
		{
			m_fTimeAnimation = 0.0f;
			m_nStatus = STATUS_CLOSE_FOREVER;
		}
	}

	// Nếu GunMachine đang mở ra.
	if (m_nStatus == STATUS_LEFT || m_nStatus == STATUS_TOP || m_nStatus == STATUS_UP)
	{
		//// Tính toán góc của bill so với vị trí của GunMachine.
		float angle = atan2(billPos.y - m_pos.y, billPos.x - m_pos.x) * 180 / PI;
		int statusAngle;
		D3DXVECTOR2 bulletPos;

		// Tính toán góc bắn và vị trí đạn.
		if (angle < 165 && angle > 135)
		{
			statusAngle = STATUS_TOP;
			m_pGun->SetBulletAngle(150);
			bulletPos.x = m_pos.x - m_pSprite->GetWidth() / 2.0f;
			bulletPos.y = m_pos.y + m_pSprite->GetHeight() / 4.0f;
		}
		else if (angle < 135 && angle > 0)
		{
			statusAngle = STATUS_UP;
			m_pGun->SetBulletAngle(120);
			bulletPos.x = m_pos.x - m_pSprite->GetWidth() / 4.0f;
			bulletPos.y = m_pos.y + m_pSprite->GetHeight() / 2.0f - 2.0f;
		}
		else
		{
			statusAngle = STATUS_LEFT;
			m_pGun->SetBulletAngle(180);
			bulletPos.x = m_pos.x - m_pSprite->GetWidth() / 2.0f;
			bulletPos.y = m_pos.y;
		}

		// Tính góc quay.
		if (m_nStatus > statusAngle)
			m_nStatus--;
		else if (m_nStatus < statusAngle)
			m_nStatus++;

		if (m_fTimeReFire > 0)
		{
			m_fTimeReFire -= timeFrame;
		}
		else
		{
			if (m_nBulletsFired == MAX_BULLETS)
			{
				m_fTimeReFire = 2.0f;
				m_nBulletsFired = 0;
			}
			else
			{
				// Khi 2 góc góc quay bằng góc bắn thì bắn.
				if (m_nStatus == statusAngle)
				{
					if (m_fTimeAnimation > 0)
						m_fTimeAnimation -= timeFrame;
					else
					{
						if (m_pGun->Fire(bulletPos))
						{
							m_fTimeAnimation = 0.2f;
							m_nBulletsFired++;
						}
					}
				}
			}
		}
		
	}

	UpdateAnimation();
	UpdateBox(timeFrame);
}

void CGunMachine::UpdateCollision(vector<CGameObject*> vecGameObjs, float timeFrame)
{
	if (!m_bIsLive || (m_nStatus != STATUS_LEFT && m_nStatus != STATUS_TOP && m_nStatus != STATUS_UP))
		return;

	float timeCollision = timeFrame;
	CGameObject* objCollision = NULL; // Đối tượng va chạm sớm nhất.
	float normalx = 0.0f, normaly = 0.0f;

	// Xử lí va chạm với đạn của Bill
	for (int i = 0; i < CPlayState::s_billBullets.size(); i++)
	{
		if (CPlayState::s_billBullets[i]->IsLive())
		{
			float t = CheckCollision(CPlayState::s_billBullets[i], normalx, normaly, timeFrame);

			if (t < timeFrame && t < timeCollision)
			{
				// Tìm đối tượng và thời gian va chạm sớm nhất.
				timeCollision = t;
				objCollision = CPlayState::s_billBullets[i];
			}
		}
	}

	// Xử lí va chạm
	if (objCollision != NULL)
	{
		this->Kill();
		objCollision->Kill();
	}
}

void CGunMachine::Draw()
{
	if (!m_bIsLive)
		return;
	D3DXVECTOR2 pos = CViewport::GetInstance()->TransformMatrix(m_pos);

	if (m_nStatus != STATUS_CLOSE_FOREVER && m_nStatus != STATUS_CAN_OPEN)
		// Phải tranform sang góc quay do góc được tính ra ở trên khác.
		m_pSprite->Draw(pos);
}

bool CGunMachine::Kill()
{
	if (m_nStatus == STATUS_LEFT || m_nStatus == STATUS_TOP || m_nStatus == STATUS_UP)
	{
		if (m_nLife > 1)
			m_nLife--;
		else
		{
			m_bIsLive = false;
			CExplosion* explosion = new CExplosion(m_pos, 0, ID_SMALL_EXPLOSION);
			CPlayState::s_objsOutSideQuadTree.push_back(explosion);
		}

		return true;
	}

	return false;
}